package tools

import (
	"encoding/json"
	"fmt"
	"time"

	"workflow-gui/internal/database"
	"workflow-gui/internal/httpclient"
	"workflow-gui/internal/protocol"
)

// Handler handles tool execution
type Handler struct {
	registry                  *Registry
	httpClient                *httpclient.Client
	guiHandler                *GUIHandler
	aiSupplementHandler       *AISupplementHandler
	aiIterateHandler          *AIIterateHandler
	workflowManagementHandler *WorkflowManagementHandler
	taskExecutionHandler      *TaskExecutionHandler
	timeout                   time.Duration
}

// NewHandler creates a new tool handler
func NewHandler(registry *Registry, guiURL string, db *database.DB, projectRoot string) (*Handler, error) {
	// Create GUI handler
	guiHandler := NewGUIHandler(projectRoot)

	// Create AI supplement handler (only if db is provided)
	var aiSupplementHandler *AISupplementHandler
	var aiIterateHandler *AIIterateHandler
	var workflowManagementHandler *WorkflowManagementHandler
	var taskExecutionHandler *TaskExecutionHandler
	var err error

	if db != nil {
		aiSupplementHandler, err = NewAISupplementHandler(db)
		if err != nil {
			return nil, fmt.Errorf("failed to create AI supplement handler: %w", err)
		}

		// Create AI iterate handler (reuse AI client and prompt engine from supplement handler)
		aiIterateHandler = NewAIIterateHandler(db, aiSupplementHandler.aiClient, aiSupplementHandler.promptEngine)

		// Create workflow management handler
		workflowManagementHandler = NewWorkflowManagementHandler(db)

		// Create task execution handler (reuse AI client and prompt engine)
		taskExecutionHandler = NewTaskExecutionHandler(db, aiSupplementHandler.aiClient, aiSupplementHandler.promptEngine)
	}

	return &Handler{
		registry:                  registry,
		httpClient:                httpclient.NewClient(guiURL),
		guiHandler:                guiHandler,
		aiSupplementHandler:       aiSupplementHandler,
		aiIterateHandler:          aiIterateHandler,
		workflowManagementHandler: workflowManagementHandler,
		taskExecutionHandler:      taskExecutionHandler,
		timeout:                   120 * time.Second,
	}, nil
}

// HandleToolCall handles a tool call request
func (h *Handler) HandleToolCall(name string, arguments map[string]interface{}) (protocol.ToolResult, error) {
	// Check if tool exists
	_, ok := h.registry.GetTool(name)
	if !ok {
		return protocol.NewErrorResult(fmt.Sprintf("Unknown tool: %s", name)), nil
	}

	// Route to specific handler
	switch name {
	case "open_gui":
		return h.guiHandler.HandleOpenGUI(arguments)
	case "create_workflow":
		return h.handleCreateWorkflow(arguments)
	case "ai_supplement_stage1":
		if h.aiSupplementHandler == nil {
			return protocol.NewErrorResult("AI supplement handler not initialized"), nil
		}
		return h.aiSupplementHandler.HandleAISupplementStage1(arguments)
	case "ai_supplement_stage2":
		if h.aiSupplementHandler == nil {
			return protocol.NewErrorResult("AI supplement handler not initialized"), nil
		}
		return h.aiSupplementHandler.HandleAISupplementStage2(arguments)
	case "ai_supplement_stage3":
		if h.aiSupplementHandler == nil {
			return protocol.NewErrorResult("AI supplement handler not initialized"), nil
		}
		return h.aiSupplementHandler.HandleAISupplementStage3(arguments)
	case "ai_iterate_stage1":
		if h.aiIterateHandler == nil {
			return protocol.NewErrorResult("AI iterate handler not initialized"), nil
		}
		return h.aiIterateHandler.HandleAIIterateStage1(arguments)
	case "ai_iterate_stage2":
		if h.aiIterateHandler == nil {
			return protocol.NewErrorResult("AI iterate handler not initialized"), nil
		}
		return h.aiIterateHandler.HandleAIIterateStage2(arguments)
	case "ai_iterate_stage3":
		if h.aiIterateHandler == nil {
			return protocol.NewErrorResult("AI iterate handler not initialized"), nil
		}
		return h.aiIterateHandler.HandleAIIterateStage3(arguments)
	case "list_workflows":
		if h.workflowManagementHandler == nil {
			return protocol.NewErrorResult("Workflow management handler not initialized"), nil
		}
		return h.workflowManagementHandler.HandleListWorkflows(arguments)
	case "get_workflow":
		if h.workflowManagementHandler == nil {
			return protocol.NewErrorResult("Workflow management handler not initialized"), nil
		}
		return h.workflowManagementHandler.HandleGetWorkflow(arguments)
	case "execute_task":
		if h.taskExecutionHandler == nil {
			return protocol.NewErrorResult("Task execution handler not initialized"), nil
		}
		return h.taskExecutionHandler.HandleExecuteTask(arguments)
	case "save_stage1_results":
		if h.aiSupplementHandler == nil {
			return protocol.NewErrorResult("AI supplement handler not initialized"), nil
		}
		return h.aiSupplementHandler.HandleSaveStage1Results(arguments)
	case "save_stage2_results":
		if h.aiSupplementHandler == nil {
			return protocol.NewErrorResult("AI supplement handler not initialized"), nil
		}
		return h.aiSupplementHandler.HandleSaveStage2Results(arguments)
	case "save_stage3_results":
		if h.aiSupplementHandler == nil {
			return protocol.NewErrorResult("AI supplement handler not initialized"), nil
		}
		return h.aiSupplementHandler.HandleSaveStage3Results(arguments)
	default:
		return protocol.NewErrorResult(fmt.Sprintf("Tool not implemented: %s", name)), nil
	}
}

// handleCreateWorkflow handles the create_workflow tool
func (h *Handler) handleCreateWorkflow(args map[string]interface{}) (protocol.ToolResult, error) {
	// Extract arguments
	summary, ok := args["summary"].(string)
	if !ok || summary == "" {
		return protocol.NewErrorResult("Missing required argument: summary"), nil
	}

	motivation, ok := args["motivation"].(string)
	if !ok || motivation == "" {
		return protocol.NewErrorResult("Missing required argument: motivation"), nil
	}

	// Call GUI service
	request := map[string]interface{}{
		"summary":    summary,
		"motivation": motivation,
	}

	response, err := h.httpClient.CreateWorkflow(request, h.timeout)
	if err != nil {
		return protocol.NewErrorResult(fmt.Sprintf("Failed to create workflow: %v", err)), nil
	}

	// Check if cancelled
	if cancelled, ok := response["cancelled"].(bool); ok && cancelled {
		return protocol.NewErrorResult("User cancelled the operation"), nil
	}

	// Check for error
	if errMsg, ok := response["error"].(string); ok && errMsg != "" {
		return protocol.NewErrorResult(fmt.Sprintf("Error: %s", errMsg)), nil
	}

	// Extract result
	result, ok := response["result"].(map[string]interface{})
	if !ok {
		return protocol.NewErrorResult("Invalid response from GUI service"), nil
	}

	// Format success message
	changeID, _ := result["change_id"].(string)
	complexity, _ := result["complexity"].(string)

	message := fmt.Sprintf("✅ 工作流创建成功！\n\nID: %s\n名称: %s\n复杂度: %s\n\n系统已自动生成工作流配置。",
		changeID, summary, complexity)

	return protocol.NewSuccessResult(message), nil
}

// MarshalArguments marshals arguments to JSON
func MarshalArguments(args interface{}) (map[string]interface{}, error) {
	data, err := json.Marshal(args)
	if err != nil {
		return nil, err
	}

	var result map[string]interface{}
	if err := json.Unmarshal(data, &result); err != nil {
		return nil, err
	}

	return result, nil
}
